#include "cmd_fsc.h"


#define EXT_DAT_LEN         (64)
#define BUF_LEN             (EXT_DAT_LEN + 8)

#define PAC_LENGTH          (uint32_t)(256)

/* 功能 宏定义 */
#define CMD_HEAD            0x3A        //命令头

/* 指令定义 */
#define CMD_INTERRUPT       0x00        //中断
#define CMD_QUERYINFO       0x01        //查询
#define CMD_CAPTURE         0x02        //采集
#define CMD_ENROLL          0x03        //注册(简化)
#define CMD_ENROLL_EX       0x13        //注册(常用)
#define CMD_MATCH           0x04        //比对
#define CMD_MATCH_EX        0x14        //注册(常用)
#define CMD_DELETE          0x05        //删除
#define CMD_TRANSMIT        0x06        //数据传输
#define CMD_CONFIG          0x07        //系统配置
#define CMD_WRITEREG        0x09        //寄存器读写
#define CMD_VERSION         0x0A        //系统版本

typedef struct _CMD_DATA_S
{
    uint8_t *Data;
    uint16_t Len;
} CMD_DATA;

typedef struct
{
    uint8_t   Head;
    uint8_t   Cmd;                  //指令
    uint16_t  Func;                 //功能码
    uint16_t  Len;
    uint8_t   XOR;
    uint8_t   ExtData[EXT_DAT_LEN]; //扩展域
    uint8_t   SUM;
} CmdPacket;

typedef union
{
    uint8_t   Buf[BUF_LEN];
    CmdPacket Packet;
} UartData;

typedef enum
{
    IDLE_USART = 0,     //USART空闲状态
    HANDLE_USART        //USART处理状态
} PacketStatus;

typedef struct          //串口相关参数
{
    volatile PacketStatus Status;
    void (*PutString) (uint8_t buf[],uint32_t len);
    void (*GetString) (uint8_t buf[],uint32_t len);
} UartParas;

typedef union
{
    struct
    {
        uint16_t num;
        uint16_t len;
    } pack;
} TransTypedef;

UartParas g_UartParas;

static UartData Rx,Tx;      //通信协议的接收发送buffer
uint8_t gInterrupt = 0;
uint8_t gReset = 0;

static uint8_t Run_XOR(uint8_t *buf,uint16_t len)
{
    uint16_t i;
    uint8_t value;

    for(value=0,i=0; i<len; i++)
        value ^= buf[i];

    return value;
}

static uint8_t Run_SUM(uint8_t *buf,uint16_t len)
{
    uint16_t i;
    uint8_t value;

    for(value=0,i=0; i<len; i++)
        value += buf[i];

    return (~value);
}

static uint16_t swap_byte(uint16_t data)
{
    uint8_t high = (uint8_t) (data >> 8);
    uint8_t low = (uint8_t) (data);
    return (low << 8) | (high);
}

uint16_t QueryInfo(uint16_t Ctrl, CMD_DATA *CMD, CMD_DATA *ACK_Para)
{
    uint16_t len = 0;
	
    ACK_Para->Len = len;
    return RET_OK;
}

uint16_t ConfigParams(uint16_t Ctrl, CMD_DATA *CMD, CMD_DATA *ACK)
{
	gReset=1;
    return RET_OK;
}

static void ResponseCommand(UartData *ACK)
{
    ACK->Packet.XOR = Run_XOR(ACK->Buf, 6);

    ACK->Packet.SUM = Run_SUM(ACK->Buf, (ACK->Packet.Len +7) );
    ACK->Buf[ ACK->Packet.Len+7 ] = ACK->Packet.SUM;
    ACK->Packet.Func = swap_byte(ACK->Packet.Func);
    uint16_t len = ACK->Packet.Len;
    ACK->Packet.Len = swap_byte(len);

    g_UartParas.PutString(ACK->Buf, len+8);
}

uint16_t TransmitData(uint16_t Ctrl, CMD_DATA* CMD, CMD_DATA* ACK)
{
    uint16_t data_len=0;
    uint8_t tempbuf[PAC_LENGTH];
    TransTypedef par= {{0,0}};
    UartData DataPack;
	uint32_t temp;

    if(CMD->Len < 4)
        return ERROR_PAR;

    par.pack.num = CMD->Data[1] | (CMD->Data[0]<<8);
    par.pack.len = CMD->Data[3] | (CMD->Data[2]<<8);

    /* 需要传输的数据地址 */
	
    if((Ctrl & BIT_06) || (Ctrl & BIT_01))
    {
        data_len = par.pack.len;
    }
    else if (Ctrl & (BIT_15 | BIT_09 | BIT_14))
    {
        data_len = par.pack.len;
    }

//	if(Ctrl & (BIT_00))
//	{
//		ACK->Len  = 0;
//		//
//		temp = CMD->Data[2]<<24;
//		temp += CMD->Data[3]<<16;
//		temp += CMD->Data[4]<<8;
//		temp += CMD->Data[5];
//		data_len = IAP_CRC(IAP_CODE_SIZE, temp);
//		if(data_len != par.pack.num)
//		{
//			_IAP_Erase(IAP_PAGE_ERASE, IAP_CODE_SIZE, LIBCFG_FLASH_SIZE);
//			return ERROR_PAR;
//		}
//		gReset = 1;
//		return RET_OK;
//	}
    /*识别数据包的应答*/
    DataPack.Packet.Head = CMD_HEAD;
    DataPack.Packet.Cmd  = CMD_TRANSMIT;
    DataPack.Packet.Func = RET_OK;
    DataPack.Packet.Len = 2;
    DataPack.Packet.ExtData[0] = (Ctrl>>8);
    DataPack.Packet.ExtData[1] = Ctrl;
    ResponseCommand(&DataPack);

    if (Ctrl & (BIT_15))
    {
        /** 上传8-BIT数据 */
        //FSC_ReadImage(par.pack.num * PAC_LENGTH, tempbuf, data_len);
        g_UartParas.PutString(tempbuf, data_len);
    }
    else if (Ctrl & BIT_09)
    {
    }
    else if (Ctrl & BIT_06)
    {
    }
    else if (Ctrl & (BIT_14))
    {
        /** 下载数据 */
        g_UartParas.GetString(tempbuf, data_len);
        //FSC_WriteImage(par.pack.num * PAC_LENGTH, tempbuf, data_len);
    }
//    else if(Ctrl & (BIT_01) )
//    {
//		g_UartParas.GetString(tempbuf, data_len);
//		if(par.pack.num == 0)
//		{
//			_IAP_Erase(IAP_PAGE_ERASE, IAP_CODE_SIZE, LIBCFG_FLASH_SIZE);
//		}
//		temp = IAP_CODE_SIZE + PAC_LENGTH * par.pack.num;
//		IAP_Flash(CMD_PROGRAM, temp, temp+data_len, tempbuf);
//    }

    ACK->Len  = 4;
    ACK->Data[0] = Ctrl>>8;
    ACK->Data[1] = Ctrl;
	if(Ctrl & BIT_00)
	{
        ACK->Data[2] = data_len>>8;
        ACK->Data[3] = data_len;
	}
    else if(Ctrl & BIT_12) /*不返回校验数据*/
    {
        ACK->Data[2] = 0;
        ACK->Data[3] = 0;
    }
    else              /*返回校验数据*/
    {
        ACK->Data[2] = Run_XOR(tempbuf, data_len);
        ACK->Data[3] = Run_SUM(tempbuf, data_len);
    }

    return RET_OK;
}
/* 校验指令 */
int8_t CheckCommand(CmdPacket *RxPack, CmdPacket *TxPack)
{
    TxPack->Head = RxPack->Head;
    TxPack->Cmd  = RxPack->Cmd;
    TxPack->Len  = 0;

    if(Run_XOR((uint8_t *)RxPack, 6) != RxPack->XOR)
    {
        TxPack->Func = ERROR_XOR;
        return -1;
    }
    else if(Run_SUM((uint8_t *)RxPack, RxPack->Len +7) != RxPack->SUM)
    {
        TxPack->Func = ERROR_SUM;
        return -1;
    }
    else
        return 0;
}

void ProcessCommand(CmdPacket* CMD_Pack, CmdPacket* ACK_Pack)
{
    uint8_t   TempCmd;
    CMD_DATA  CMD_Par;
    CMD_DATA  ACK_Par;
    uint16_t  ctrl = CMD_Pack->Func;
    uint16_t  result = ERROR_CMD;
    CMD_Par.Len  = CMD_Pack->Len;
    CMD_Par.Data = CMD_Pack->ExtData;
    ACK_Par.Len  = 0;
    ACK_Par.Data = ACK_Pack->ExtData;

    TempCmd = CMD_Pack->Cmd;
	gInterrupt = 0;
	switch(TempCmd)
	{
	case CMD_INTERRUPT:
		break;
	case CMD_QUERYINFO:
		result = QueryInfo(ctrl, &CMD_Par, &ACK_Par);
		break;
	case CMD_DELETE:
		break;
	case CMD_CONFIG:
		result = ConfigParams(ctrl, &CMD_Par, &ACK_Par);
		break;
	case CMD_WRITEREG:
		break;
	case CMD_VERSION:
		break;
	case CMD_CAPTURE:
		break;
	case CMD_TRANSMIT:
		result = TransmitData(ctrl, &CMD_Par, &ACK_Par);
		break;
	case CMD_MATCH:
	case CMD_MATCH_EX:
		break;
	case CMD_ENROLL:
		break;
	case CMD_ENROLL_EX:
		break;
	default:
		result = ERROR_CMD;
		break;
	}
	
    {
        ACK_Pack->Cmd  = TempCmd;
        ACK_Pack->Func = result;
        ACK_Pack->Len  = ACK_Par.Len;
        if( ACK_Par.Len != 0 )
            memcpy(ACK_Pack->ExtData, ACK_Par.Data, ACK_Par.Len);
    }
}

void FSC_CmdHandler(void)
{
    if(g_UartParas.Status == IDLE_USART)      //判断是否有完整指令包
        return;

    if(g_UartParas.PutString != USART_PutString)
    {
        g_UartParas.PutString = USART_PutString;
//        g_UartParas.GetString = USART_GetString;
    }

    if(0 == CheckCommand(&Rx.Packet, &Tx.Packet))
    {
        ProcessCommand(&Rx.Packet, &Tx.Packet);
    }

	if(g_UartParas.Status != IDLE_USART)
	{
		ResponseCommand(&Tx);
//		IAP_DELAY(5);
		g_UartParas.Status = IDLE_USART;
	}
	
	if(gReset)
		_IAP_Reset(1);
}

void FSC_DataHandler(uint8_t Data)
{
    static uint32_t RxCount =0;
    uint16_t len;

    Rx.Buf[RxCount] = Data;         //缓存数据

    if( Rx.Packet.Head == CMD_HEAD)
    {
		FSC_SetState(STATE_PRO_FLAG, 1);
        RxCount ++;
        if ((RxCount >= 2) && !((Rx.Packet.Cmd <= CMD_MATCH_EX)))
        {
            RxCount = 0;
			FSC_SetState(STATE_PRO_FLAG, 0);
            return;
        }

        if(RxCount > BUF_LEN)       //越界处理
        {
            RxCount = 0;
        }
        else if (RxCount >= 8)      //接收8个byte后才判断，是否有扩展域
        {
            len = swap_byte(Rx.Packet.Len);
            if (len > 8)
            {
                RxCount = 0;
				FSC_SetState(STATE_PRO_FLAG, 0);
                return;
            }
            if(RxCount == (len + 8))//指令接收完成
            {
                Rx.Packet.SUM = Rx.Buf[RxCount-1];
                RxCount = 0;

                g_UartParas.Status = HANDLE_USART;

                Rx.Packet.Func = swap_byte(Rx.Packet.Func);
                Rx.Packet.Len = swap_byte(Rx.Packet.Len);

                /* 快速判断是否为中断指令 */
                if( (Rx.Packet.Cmd == Rx.Packet.Func == Rx.Packet.Len == 0) &&
                        (Rx.Packet.XOR == 0x3A) && (Rx.Packet.SUM == 0x8B) )
                {				
                    USART_PutString(Rx.Buf, 8);
                    g_UartParas.Status = IDLE_USART;
					gInterrupt = 1;
                }
				FSC_SetState(STATE_PRO_FLAG, 0);
            }
        }
    }
    else
    {
		FSC_SetState(STATE_PRO_FLAG, 0);
        RxCount = 0;
    }
}
//
static int8_t sysState[STATE_INDEX_MAX];
void FSC_SetState(uint8_t n, int8_t state)
{
	if(n < STATE_INDEX_MAX)
		sysState[n] = state;
}

int8_t FSC_GetState(uint8_t n)
{
	if(n < STATE_INDEX_MAX)
		return sysState[n];
	return -1;
}
// uint8_t Test_Sram=0;
en_result_t Test_FLAG;
uint32_t _IAP_Reset(uint32_t uMode)
{
  if (uMode == 0)
  {

    Flash_WriteByte(BOOT_MODE_ID_ADDR, BOOT_MODE_AP);
  }
  else
  {
	  Flash_SectorErase(BOOT_MODE_ID_ADDR);
      Flash_WriteByte(BOOT_MODE_ID_ADDR, BOOT_MODE_IAP);
	  
  }
  NVIC_SystemReset();
  return TRUE;
}
